package com.github.caiqy.shirodemo.config;

import com.github.caiqy.shirodemo.db.mapping.PathDefinition;
import com.github.caiqy.shirodemo.db.service.PathDefinitionService;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.AbstractShiroWebFilterConfiguration;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import javax.servlet.Filter;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

@Configuration
public class ShiroCoreConfig extends AbstractShiroWebFilterConfiguration {

    private PathDefinitionService pathDefinitionService;

    @Autowired
    public ShiroCoreConfig(PathDefinitionService pathDefinitionService) {
        this.pathDefinitionService = pathDefinitionService;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
//        creator.setProxyTargetClass(true);
        creator.setUsePrefix(true);
        return creator;
    }

    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(RolesOrFilter rolesOrFilter) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = super.shiroFilterFactoryBean();
        shiroFilterFactoryBean.setFilters(new HashMap<String, Filter>() {
            {
                this.put("rolesOr", rolesOrFilter);
            }
        });
        return shiroFilterFactoryBean;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        List<PathDefinition> list = pathDefinitionService.selectAll();
        if (CollectionUtils.isEmpty(list)) {
            return chainDefinition;
        }
        list.stream().sorted(Comparator.comparingInt(PathDefinition::getIndex)).forEach(pd -> {
            chainDefinition.addPathDefinition(pd.getPathPattern(), pd.getAuthorization());
        });
        return chainDefinition;
    }
}
